if(!window.xflib || !window.xflib.client) window.xflib = { client: {} }

xflib.client.ProjectService = class ProjectService {

    constructor(storage) {
        this.toArray = window.xflib.client.toArray;
        this.storage = storage;
    }

    async create(projectCode, projectName, projectUrl, projectCategory, projectSerial, permissions = [], productCode = '') {
        if (projectCode && projectName) {
            return this.storage.instance.get("projects").then((data) => {
                const projects = data.projects || {};
                if (Object.keys(projects).includes(projectCode) && projects[projectCode].name === projectName) {
                    return Promise.reject("项目已存在.");
                }
                return this.storage.instance.set({
                    projects: {
                        ...projects,
                        [projectCode]: {
                            name: projectName,
                            url: projectUrl,
                            category: projectCategory,
                            serial: projectSerial,
                            permissions: permissions,
                            productCode: productCode
                        }
                    }
                });
            }).catch((error) => {
                return Promise.reject(error.message);
            });
        }
        return Promise.reject("项目代码和名称不能为空.");
    }

    async updateBatch(projects){
        return this.storage.instance.set({projects: projects});
    }

    async update(projectOldCode, projectCode, projectName, projectUrl, projectCategory, projectSerial, permissions = [], productCode = '') {
        if (projectCode && projectName) {
            return this.storage.instance.get("projects").then((data) => {
                const projects = data.projects || {};
                if (projects && projects[projectOldCode]) {
                    delete projects[projectOldCode];
                }
                return this.storage.instance.set({
                    projects: {
                        ...projects,
                        [projectCode]: {
                            name: projectName,
                            url: projectUrl,
                            category: projectCategory,
                            serial: projectSerial,
                            permissions: permissions,
                            productCode: productCode
                        }
                    }
                });
            }).catch((error) => {
                return Promise.reject(error.message);
            });
        }
        return Promise.reject("项目代码和名称不能为空.");
    }

    async delete(projectCodes) {
        if(projectCodes){
            return this.storage.instance.get("projects").then((data)=>{
                const projects = data.projects || {};
                this.toArray(projectCodes).forEach((projectCode)=>{
                    if(projects && projects[projectCode]){
                        delete projects[projectCode];   
                    }
                });
                return this.storage.instance.set({projects: projects});
            }).catch((error)=>{
                return Promise.reject(error.message);
            });
        }
        return Promise.reject("cannot null or empty project codes.");
    }

    async clear() {
        return this.storage.instance.clear("projects");
    }
    
    exportProjects(productCode, category) {
        // 假设 projects 是从某个服务或状态管理中获取的项目数据
        const projectService = this;//new xflib.client.ProjectService(new xflib.client.Storage(false, true));
    
        // 获取项目数据
        if(category === 'all' && productCode === 'all'){
            projectService.queryByProjectCode()
            .then(projects => this.exportByProducts(projects))
            .catch(error => console.error('导出项目失败:', error));
        }else if(category === 'all'){
            projectService.queryProjectsByProductCode(productCode)
            .then(projects => this.exportByProducts(projects))
            .catch(error => console.error('导出项目失败:', error));
        } else if(productCode === 'all'){
            projectService.queryByCategory(category)
            .then(projects => this.exportByProducts(projects))
            .catch(error => console.error('导出项目失败:', error));
        } else {
            projectService.queryProjectsByProductCodeAndCategory(productCode, category)
            .then(projects => this.exportByProducts(projects))
            .catch(error => console.error('导出项目失败:', error));
        }

    }

    exportByProducts(projects) {
        const projectsData = {
            projects: [],
            categories: [],
            products: []
        };

        const usedCategories = new Set(); // 用于存储使用过的分类
        const usedProducts = new Set(); // 用于存储使用过的产品

        const categoryService = window.xflib.client.Application.getBean('categoryService');
        const productService = window.xflib.client.Application.getBean('productService');

        for (const [code, project] of Object.entries(projects)) {
            console.log(project || 'err');
            projectsData.projects.push({
                code: code, // 添加项目代码
                name: project.name,
                category: project.category,
                url: project.url,
                permissions: this.toArray(project.permissions),
                productCode: project.productCode,
                serial: project.serial
            });

            // 收集使用过的分类和产品
            usedCategories.add(project.category);
            usedProducts.add(project.productCode);
        }

        // 获取分类数据
        categoryService.queryByCategoryCodes().then(categories => {
            // 过滤出在项目中使用过的分类
            projectsData.categories = Object.entries(categories).filter((category) => usedCategories.has(category[0]));

            // 获取产品数据
            productService.queryByProductCodes().then(products => {
                // 过滤出在项目中使用过的产品
                projectsData.products = Object.entries(products).filter((product) => usedProducts.has(product[0]));

                // 将项目数据转换为 JSON 字符串
                const jsonString = JSON.stringify(projectsData, null, 2);

                // 创建一个 Blob 对象并生成下载链接
                const blob = new Blob([jsonString], { type: 'application/json' });
                const url = URL.createObjectURL(blob);

                // 创建一个临时链接并触发下载
                const a = document.createElement('a');
                a.href = url;
                a.download = 'projects_export.json';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url); // 释放 URL 对象
            }).catch(error => {
                console.error('获取产品数据失败:', error);
            });
        }).catch(error => {
            console.error('获取分类数据失败:', error);
        });
    }

    importProjects(file) {

    
        const reader = new FileReader();
        reader.onload = async function(e) {
            const errorLog = []; // 用于记录错误日志
            try {
                const data = JSON.parse(e.target.result); // 解析 JSON 数据
    
                // 检查 categories, products 和 projects 是否存在
                // if (!Array.isArray(data.categories) || !Array.isArray(data.products) || !Array.isArray(data.projects)) {
                //     throw new Error('文件格式不正确，请确保包含 categories, products 和 projects 数组');
                // }
    
                const projectService = window.xflib.client.Application.getBean('projectService');//new xflib.client.ProjectService(new xflib.client.Storage(false, true));
                const categoryService = window.xflib.client.Application.getBean('categoryService');//new xflib.client.CategoryService(new xflib.client.Storage(false, true));
                const productService = window.xflib.client.Application.getBean('productService');//new xflib.client.ProductService(new xflib.client.Storage(false, true));
    
                // 导入分类
                for (const category of data.categories) {
                    // try {
                        await categoryService.create(category.code, category.name).catch((error)=>{
                            errorLog.push(`导入分类 ${category.code} 失败:  ${JSON.stringify(category)}`); //${error.message}
                        }); // 假设 create 方法存在
                    // } catch (error) {
                    //     errorLog.push(`导入分类 ${category.code} 失败: ${error.message}`);
                    // }
                }
    
                // 导入产品
                for (const product of data.products) {
                    // try {
                        await productService.create(product.code, product.name).catch((error)=>{
                            errorLog.push(`导入产品 ${product.code} 失败: ${JSON.stringify(product)}`); //  ${error.message}
                        }); // 假设 create 方法存在
                    // } catch (error) {
                    //     errorLog.push(`导入产品 ${product.code} 失败: ${error.message}`);
                    // }
                }
    
                // 导入项目
                for (const project of data.projects) {
                    try {
                        await projectService.create(project.code, project.name, project.url, project.category, project.serial, project.permissions, project.productCode);
                    } catch (error) {
                        errorLog.push(`导入项目 ${project.code} 失败:  ${JSON.stringify(project)}`); //${error.message}
                    }
                }
    
                alert('导入完成');
    
                // 如果有错误日志，提示下载
                if (errorLog.length > 0) {
                    const errorLogString = errorLog.join('\n');
                    const blob = new Blob([errorLogString], { type: 'text/plain' });
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = 'error_log.txt';
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url); // 释放 URL 对象
                    alert('导入完成，存在错误日志，请下载 error_log.txt');
                } else {
                    alert('导入完成，没有错误。');
                }
            } catch (error) {
                alert('文件格式不正确，请确保上传的是有效的 JSON 文件');
                console.error('导入项目失败:', error);
            }
        };
    
        reader.readAsText(file); // 读取文件内容
    }

    async deleteByProductAndCategory(productCode, category, deleteGroup = false) {
        return this.storage.instance.get("projects").then((data) => {
            const projects = data.projects || {};
            const projectsToDelete = Object.entries(projects)
                .filter(([_, project]) => project.productCode === (productCode === 'all'?project.productCode:productCode) &&
                                            project.category === (category === 'all'?project.category:category));

            // 删除项目
            projectsToDelete.forEach(([code]) => {
                delete projects[code];
            });

            // 如果需要删除分组
            if (deleteGroup) {
                // 这里可以添加逻辑来删除分组，具体实现取决于您的数据结构
                // 例如，可能需要删除某个特定的分组数据
            }

            return this.storage.instance.set({ projects });
        });
    }

    async queryByProjectCode(projectCode = "projects") {
        return this.storage.instance.get("projects").then((data)=>{
            if(projectCode === "projects"){
                return data.projects;
            } else {
                return data.projects[projectCode];
            }
        });
    }

    async queryByProductCode(productCode) {
        return this.storage.instance.get("projects").then((data) => {
            const projects = data.projects || {};
            return Object.fromEntries(Object.entries(projects)
                .filter(([_, project]) => project.productCode === productCode)/*
                .map(([code, project]) => ({ code, ...project }))*/);
        });
    }

    async queryByProductCodeAndCategory(productCode, category) {
        return this.storage.instance.get("projects").then((data) => {
            const projects = data.projects || {};
            return Object.fromEntries(Object.entries(projects)
                .filter(([_, project]) => project.productCode === productCode && project.category === category)/*
                .map(([code, project]) => ({ code, ...project }))*/);
        });
    }

    async queryByCategory(category) {
        return this.storage.instance.get("projects").then((data) => {
            const projects = data.projects || {};
            return Object.fromEntries(Object.entries(projects)
                .filter(([_, project]) => project.category === category)/*
                .map(([code, project]) => ({ code, ...project }))*/);
        });
    }

    async checkAndCleanUnusedCategoriesAndProducts() {
        const projects = await this.storage.instance.get("projects").then(data => data.projects || {});
        const usedCategories = new Set(Object.values(projects).map(project => project.category));
        const usedProducts = new Set(Object.values(projects).map(project => project.productCode));

        const categoryService = window.xflib.client.Application.getBean('categoryService');
        const productService = window.xflib.client.Application.getBean('productService');

        const allCategories = (await categoryService.queryByCategoryCodes())||[];
        const allProducts = (await productService.queryByProductCodes())||[];

        const unusedCategories = Object.entries(allCategories).filter(item => !usedCategories.has(item[0]));
        const unusedProducts = Object.entries(allProducts).filter(item => !usedProducts.has(item[0]));

        return {
            result: (unusedCategories.length + unusedProducts.length) >0, 
            unusedCategories:  unusedCategories.map(([code, name]) => ({ code, name })), 
            unusedProducts: unusedProducts.map(([code, name]) => ({ code, name }))
        };

    }

}

